package org.sunyaxing.transflow.transflowapp.plugins.inputs;

import com.alibaba.fastjson2.JSONObject;
import com.sun.tools.attach.VirtualMachine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sunyaxing.transflow.api.HandleData;
import org.sunyaxing.transflow.api.TransData;
import org.sunyaxing.transflow.api.common.Handle;
import org.sunyaxing.transflow.api.common.ano.Extension;
import org.sunyaxing.transflow.api.common.ano.JobParamItem;
import org.sunyaxing.transflow.api.common.ano.ScopeContentCheck;
import org.sunyaxing.transflow.api.extensions.base.ExtensionContext;
import org.sunyaxing.transflow.api.extensions.base.types.TransFlowInput;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

@Extension("plugin-transflow-agent-input")
@ScopeContentCheck(value = {
        @JobParamItem(field = "servername", label = "服务", defaultValue = "TransflowAppApplication"),
        @JobParamItem(field = "packages", label = "扫描包", defaultValue = "org.sunyaxing.transflow.transflowapp"),
})
public class TransflowAgentExt extends TransFlowInput<String, String> {
    private static final Logger logger = LoggerFactory.getLogger(TransflowAgentExt.class);
    private final List<VirtualMachine> loadedMachines;
    private String agentPath;

    public TransflowAgentExt(ExtensionContext extensionContext) {
        super(extensionContext);
        this.loadedMachines = new ArrayList<>();
    }

    @Override
    public void commit(HandleData<String> handleData) {

    }

    @Override
    protected void afterInitHandler(JSONObject config, List<Handle> handles) {
        String name = config.getString("servername");
        String packages = config.getString("packages");
        agentPath = config.getOrDefault("agentpath","/opt/transflow/agent/agent-plugin-1.0.jar").toString();
        VirtualMachine.list()
                .stream()
                .filter(virtualMachineDescriptor -> {
                    logger.info("list {} : {}", virtualMachineDescriptor.id(), virtualMachineDescriptor.displayName());
                    return virtualMachineDescriptor.displayName().contains(name);
                })
                .findFirst()
                .ifPresent(virtualMachineDescriptor -> {
                    logger.info("attach to {} : {}", virtualMachineDescriptor.id(), virtualMachineDescriptor.displayName());
                    try {
                        VirtualMachine virtualMachine = VirtualMachine.attach(virtualMachineDescriptor.id());
                        virtualMachine.loadAgent(agentPath, "model=install,packages=" + packages);
                        //virtualMachine.detach();
                        loadedMachines.add(virtualMachine);
                    } catch (Exception e) {
                        logger.error("load agent error", e);
                    } finally {
                    }
                });
    }

    @Override
    public Function<TransData<String>, String> parseHandleToConsumer(String handleId, String handleValue) {
        return null;
    }

    @Override
    public void destroy() {
        loadedMachines.forEach(virtualMachine -> {
            try {
                virtualMachine.loadAgent(agentPath, "model=uninstall");
            } catch (Exception e) {
                logger.error("uninstall agent error", e);
            } finally {
                try {
                    virtualMachine.detach();
                } catch (IOException e) {
                    logger.error("detach agent error", e);
                }
            }
        });
        loadedMachines.clear();
    }
}
